
/**
 * 视频 ID 生成器。
 * @param {String} ip IP 地址
 * @param {Number} channel 通道号
 * @returns {String}
 */
function makeId(ip, channel) {
    return `${ip}_${channel}`;
}

/**
 * 请求全屏。
 * @param {DOM Element} element
 */
function requestFullscreen(element) {
    if (element.requestFullscreen) {
        element.requestFullscreen();
    } else if (element.mozRequestFullScreen) {
        element.mozRequestFullScreen();
    } else if (element.webkitRequestFullscreen) {
        element.webkitRequestFullscreen();
    } else if (element.msRequestFullscreen) {
        element.msRequestFullscreen();
    }
}

/**
 * 根据厂商生成相应的 RTSP 地址。
 * @param {Object} options
 * @param {Number} options.channel 通道号
 * @param {String} options.ip IP 地址
 * @param {String} options.manufacture 设备厂商
 * @param {String} options.password 密码
 * @param {String} [options.port=''] 端口
 * @param {String} options.username 用户名
 */
function getVideoUrl(options) {
    let port = null;
    let url = null;
    switch (options.manufacture) {
        case 'AXIS':
            url = `rtsp://${options.username}:${options.password}@${options.ip}/axis-media/media.amp`;
            break;
        case 'dahua':
        case '大华':
            port = (options.port && options.port !== '554') ? `:${options.port}` : '';
            url = `rtsp://${options.username}:${options.password}@${options.ip}${port}/cam/realmonitor?channel=${options.channel}&subtype=0`;
            break;
        case 'haikang':
        case '海康威视':
            port = (options.port && options.port !== '554') ? `:${options.port}` : '';
            url = `rtsp://${options.username}:${options.password}@${options.ip}${port}/streaming/channels/${options.channel}01`;
            break;
        case 'uniview':
        case '宇视':
            port = (options.port && options.port !== '554') ? `:${options.port}` : '';
            url = `rtsp://${options.username}:${options.password}@${options.ip}${port}/unicast/c${options.channel}/s0/live/video`;
            break;
        case '智能矿灯':
            url = `rtsp://${options.ip}:${options.port}`;
            break;
    }
    return url;
}

export default class VideoManager {
    /**
     * 生成 VideoManager 实例。
     * @param {Object} options
     * @param {Boolean} [options.dblclickFullScreen=true] 是否允许双击将视频全屏
     * @param {String} options.hlsUrl HLS-Service 地址
     * @param {Number} [options.manifestLoadingTimeOut=65535] 载入 manifest 的超时时间，单位毫秒
     */
    constructor(options) {
        if (!Hls) {
            console.error('hls.js not loaded.');
            return;
        }
        this.dblclickFullScreen = options.dblclickFullScreen || true;
        this.hlsUrl = options.hlsUrl;
        this.manifestLoadingTimeOut = options.manifestLoadingTimeOut || 65535;
        this.videoBoxes = new Map();
    }

    /**
     * 生成视频。
     * @param {Object} options
     * @param {Number} options.channel 通道号
     * @param {String} options.ip IP 地址
     * @param {String} options.manufacture 设备厂商
     * @param {String} options.password 密码
     * @param {String} [options.port=''] 端口
     * @param {String} options.username 用户名
     * @returns {Array} [video, hls, id]
     */
    makeVideo(options) {
        const id = makeId(options.ip, options.channel);
        const url = getVideoUrl(options);
        console.log(url);
        const video = document.createElement('video');
        video.setAttribute("id",id);
        const src = `${this.hlsUrl}/streams/?src=` + encodeURIComponent(url);
        // console.log(decodeURIComponent(src))
        let hls = null;
        if (Hls && Hls.isSupported()) {
            hls = new Hls({
                manifestLoadingTimeOut: this.manifestLoadingTimeOut
            });
            hls.loadSource(src);
            hls.attachMedia(video);
            hls.on(Hls.Events.MANIFEST_PARSED, () => {
                video.play().then(() => console.log("hls play ..."));
            });
            hls.on(Hls.Events.ERROR, (event, data) => {
                if (data.fatal) {
                    switch(data.type) {
                        case Hls.ErrorTypes.NETWORK_ERROR:
                            // try to recover network error
                            hls.startLoad();
                            break;
                        case Hls.ErrorTypes.MEDIA_ERROR:
                            // try to recover media error
                            hls.recoverMediaError();
                            break;
                        default:
                            // cannot recover
                            hls.destroy();
                            break;
                    }
                }
            });
        } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
            video.src = src;
            video.addEventListener('loadedmetadata', () => {
                video.play().then(() => console.log("hls play ..."));
            });
        }else{
            console.log("hls ....");
        }
        if (this.dblclickFullScreen) {
            // 双击鼠标左键全屏，Esc 退出。
            video.addEventListener('dblclick', event => {
                requestFullscreen(event.target);
            }, false);
        }
        this.videoBoxes.set(id, {
            hls: hls,
            url: url,
            video: video
        });
        return [video, hls, id];
    }

    /**
     * 停止播放，并销毁 video 元素。
     * @param {String} id 视频 ID
     */
    removeVideo(id) {
        let videoBox = this.videoBoxes.get(id);
        if (videoBox) {
            if (videoBox.hls) {
                videoBox.hls.stopLoad();
                videoBox.hls = null;
            } else if (videoBox.video) {
                videoBox.video.pause();
            }
            videoBox.video.parentElement.removeChild(videoBox.video);
            this.videoBoxes.delete(id);
        }
    }

    /**
     * 检查视频窗口是否已打开。
     * @param {String} ip
     * @param {Number} channel
     * @returns {Boolean}
     */
    // isVideoShown(ip, channel) {
    //     const id = makeId(ip, channel);
    //     return mapManager.popups.has(id);
    // }
}
